package paystation.domain;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;

/**
 * Implementation of the pay station.
 * 
 * Responsibilities:
 * 
 * 1) Accept payment; 2) Calculate parking time based on payment; 3) Know earning, parking time bought; 4) Issue receipts; 5) Handle buy and
 * cancel events.
 */

public class PayStationImpl extends UnicastRemoteObject implements PayStation {
    private int insertedSoFar;
    private int timeBought;

    public void addPayment(int coinValue) throws IllegalCoinException, RemoteException {
        switch (coinValue) {
        case 5:
            break;
        case 10:
            break;
        case 25:
            break;
        default:
            throw new IllegalCoinException("Invalid coin: " + coinValue);
        }
        insertedSoFar += coinValue;
        timeBought = insertedSoFar / 5 * 2;
    }

    public int readDisplay() throws RemoteException{
        return timeBought;
    }

    public Receipt buy() throws RemoteException {
        Receipt r = new StandardReceipt(timeBought, false);
        _notify(timeBought, insertedSoFar);
        reset();
        return r;
    }

    public void cancel() throws RemoteException {
        reset();
    }

    private void reset() throws RemoteException {
        timeBought = insertedSoFar = 0;
    }

    // Implementation of an Observer pattern for monitoring this
    // paystation for the PS10 exercise. The Observer pattern is
    // explained in FRS Chapter 28.

    /** Internal list of the associated listeners */
    private List<StatusListener> listeners;

    public PayStationImpl() throws RemoteException{
        reset();
        listeners = new ArrayList<StatusListener>();
    }

    public void addStatusListener(StatusListener listener) throws RemoteException {
        listeners.add(listener);
    }

    private void _notify(int time, int earned) throws RemoteException {
        StatusEvent e = new StatusEvent(time, earned);
        for (StatusListener l : listeners) {
            l.update(e);
        }
    }

}
